
// class Solution
// {
// public:
//     int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid)
//     {
//         vector<vector<int>> dp(obstacleGrid);
//         dp[0][0] = 1;
//         int line = dp.size();
//         int column = dp[0].size();

//         for(int i = 0; i < line; ++i)
//         {
//             for(int j = 0; j < column; ++j)
//             {
//                 if(obstacleGrid[i][j] == 1)
//                     dp[i][j] = 0;
//                 else
//                 {
//                     if(i - 1 >= 0)
//                         dp[i][j] += dp[i - 1][j];
//                     if(j - 1 >= 0)
//                         dp[i][j] += dp[i][j - 1];
//                 }
//             }
//         }

//         return dp[line - 1][column - 1];
//     }
// };
// #pragma once
// #include "data.h"
// #include <vector>
// #include <unistd.h>
// #include <sys/types.h>
// #include <sys/wait.h>
// #include <iostream>
// using namespace std;
// struct Pipe_Child
// {
//     size_t _wfd;
//     pid_t _id;

//     Pipe_Child(size_t wfd, pid_t id)
//         : _wfd(wfd)
//         , _id(id)
//     {}
// };enum Error
// {
//     StdinError = 1,
//     PipeError,
//     ForkError
// };#pragma once
// #include <iostream>
// using namespace std;
// void Usage(const char* first)
// {
//     cout << "ScanfError" << endl;
//     cout << "Usage:" << first << " + num(num > 0)" << endl;
// }

// bool CheckStdin(int argc, const char* argv[])
// {
//     if(argc != 2 || argv[1] <= 0)
//     {
//         Usage(argv[0]);
//         return false;
//     }
//     return true;
// }

// typedef void(* task) ();

// void PrintLog()
// {
//     cout << "printf log task" << endl;
// }

// void ReloadConf()
// {
//     cout << "reload conf task" << endl;
// }

// void ConnectMysql()
// {
//     cout << "connect mysql task" << endl;
// }

// task Task[3] = {PrintLog, ReloadConf, ConnectMysql};

// int GetNextTask()
// {
//     return rand() % 3;
// }

// void work()
// {
//     while(true)
//     {
//         uint32_t task_node = 0;
//         ssize_t n = read(0, &task_node, sizeof(task_node));
//         //读到末尾了，子进程不需要执行任务，退出
//         if(n == 0)
//         {
//             break;
//         }
//         else if(n == sizeof(task_node))
//         {
//             Task[task_node]();
//         }
//         // cout << "I am worker: " << getpid() << endl;
//         // cout << endl;
//         sleep(1);
//     }

// }processpool:processpool.cc
// 	g++ -o $@ $^ -std=c++11 -g
// .PHONY:clean
// clean:
// 	rm -rf processpool#include "process_pool.hpp"

// int main(int argc, const char* argv[])
// {
//     //命令行输入不正确
//     if(!CheckStdin(argc, argv))  {return StdinError;}

//     //创建进程
//     int num_process = stoi(argv[1]);
//     //使用智能指针保证安全
//     smartptr<process_pool> ptr_pool(num_process);
//     ptr_pool->Create();

//     srand(time(nullptr));

//     //派发任务
//     CtrlProcessPool(ptr_pool, 10);
//     //任务结束
//     ptr_pool->OverTask();
//     return 0;
// }#pragma once
// #include "child_pipe.hpp"
// #include "function.hpp"
// #include "smartptr.hpp"
// class process_pool
// {
// public:
//     process_pool(int size)
//         : _size(size)
//     {}

//     //创建管道和子进程
//     void Create()
//     {
//         //记录下父进程打开的写端
//         vector<int> last_wfds;

//         for(int i = 0; i < _size; ++i)
//         {
//             //创建管道
//             int pfd[2]{0};
//             int pret = pipe(pfd);

//             //失败
//             if(pret == -1)
//                 exit(PipeError);

//             last_wfds.push_back(pfd[1]);
//             //创建子进程,读任务，再执行
//             pid_t id = fork();

//             //失败
//             if(id == -1)
//             {
//                 exit(ForkError);
//             }
//             else if(id == 0)
//             {
//                 //关闭子进程复制父进程前几个的写端，这里顺便就也关闭了当前自己不需要的写端
//                 //确保每个子进程都与父进程是单向通信
//                 for(auto& e : last_wfds)
//                 {
//                     close(e);
//                 }
//                 dup2(pfd[0], 0);
//                 work();
//                 exit(0);
//             }

//             //father
//             close(pfd[0]);
//             //创建进程池
//             _vpool.push_back(Pipe_Child(pfd[1], id));

//         }
//     }

//     //父进程向管道发送任务码
//     void SecondTask(int task_node, int pp_node)
//     {
//         write(_vpool[pp_node]._wfd, &task_node, sizeof(task_node));
//     }

//     //负载均衡，让每个子进程平均分配到任务
//     int NextTaskPool()
//     {
//         static int n = 0;
//         int next = n++;
//         n %= _vpool.size();
//         return next;
//     }

//     //关闭写端
//     void CloseWrite()
//     {
//         for(auto& e : _vpool)
//         {
//             close(e._wfd);
//         }
//     }

//     //回收子进程
//     void WaitAll()
//     {
//         for(auto& e : _vpool)
//         {
//             waitpid(e._id, nullptr, 0);
//         }
//     }

//     //任务结束
//     void OverTask()
//     {
//         //保证不再写入，关闭写端
//         CloseWrite();
//         //回收子进程
//         WaitAll();
//     }
// private:
//     vector<Pipe_Child> _vpool;
//     int _size;
// };

// void CtrlProcessPool(smartptr<process_pool>& ptr_pool, int times)
// {
//     while(times--)
//     {
//         //拿到派发任务的编号
//         int task_node = GetNextTask();
//         //拿到进程和管道的编号
//         int pp_node = ptr_pool->NextTaskPool();
//         //派发任务
//         ptr_pool->SecondTask(task_node, pp_node);
//         sleep(1);
//     }
// }
// #pragma once
// template <class T>
// class smartptr
// {
// public:
//     smartptr(int size)
//         : _ptr(new T(size))
//     {}
//     ~smartptr()
//     {
//         delete _ptr;
//     }
//     T* operator->()
//     {
//         return _ptr;
//     }
//     T& operator*()
//     {
//         return *_ptr;
//     }
// private:
//     T* _ptr;
// };
// class Solution
// {
// public:
//     int totalFruit(vector<int>& fruits)
//     {
//         int first = 0, second = 0, cur = 0, count = 1;
//         //看开头，1 1 0 0
//         while(cur < fruits.size() && fruits[cur] == fruits[first])
//         {
//             ++cur;
//         }
//         second = cur;

//         while(cur < fruits.size())
//         {
//             //有同种水果
//             while((cur < fruits.size()) && (fruits[cur] == fruits[first] || fruits[cur] == fruits[second]))
//             {
//                 ++cur;
//             }
//             if(cur < fruits.size())
//             {
//                 count = count > cur - first ? count : cur - first;

//                 first = second;
//                 int flag = 0;

//                 for(int i = first + 1; i < cur; ++i)
//                 {
//                     if(fruits[i] != fruits[first])
//                     {
//                         flag = 1;
//                         break;
//                     }
//                 }
//                 //说明不是一种
//                 if(flag == 1)
//                 {
//                     int i = cur - 1;
//                     while(fruits[i] == fruits[i - 1])
//                     {
//                         --i;
//                     }
//                     first = i;
//                 }

//                 second = cur;
//             }
//         }
//         return count > cur - first ? count : cur - first;
//     }
// };#pragma once
// #include <cstdio>
// #include <iostream>
// #include <string>
// #include <cstring>
// #include <cerrno>
// #include <sys/types.h>
// #include <sys/stat.h>
// #include <fcntl.h>
// #include <unistd.h>
// using namespace std;
// #define Path "./fifo"
// #define Mode 0666
// //希望这个类帮助我们来完成创建管道文件
// class Fifo
// {
// public:
//     Fifo(string&& pathname)
//         : _pathname(pathname)
//     {
//         umask(0);
//         int n = mkfifo(_pathname.c_str(), Mode);
//         if(n == -1)
//         {
//             cout << "create pipe file fail" << endl;
//             cerr << "errno : " << errno << ", strerror : " << strerror(errno) << endl;
//             exit(-1);
//         }
//         cout << "create pipe file success" << endl;
//     }
//     ~Fifo()
//     {
//         unlink(GetString());
//     }

//     const char* GetString()
//     {
//         return _pathname.c_str();
//     }
// private:
//     string _pathname;
// };#include "common.hpp"
// //在读文件中需要创建管道文件
// //此时读文件只需要读取管道文件的数据
// int main()
// {
//     //创建管道文件
//     Fifo fifo(Path);

//     //打开管道文件
//     int fd = open(Path, O_RDONLY);
//     if(fd == -1)
//     {
//         cout << "use read open pipe file fail" << endl;
//         cerr << "errno : " << errno << ", strerror : " << strerror(errno) << endl;
//         exit(-1);
//     }
//     cout << "read open pipe file success" << endl;
//     char buffer[1024] = "\0";
//     //开始读取
//     while(true)
//     {
//         ssize_t n = read(fd, buffer, sizeof(buffer) - 1);

//         if(n == -1)
//         {
//             cout << "read pipe file fail" << endl;
//             cerr << "errno : " << errno << ", strerror : " << strerror(errno) << endl;
//             exit(-1);
//         }
//         else if(n == 0)
//         {
//             cout << "write success exit" << endl;
//             break;
//         }

//         buffer[sizeof(buffer)] = '\0';
//         cout << "Get message: " << buffer << endl;
//     }

//     close(fd);
//     return 0;
// }#include "common.hpp"
// //写文件只需要向管道文件的传入数据
// int main()
// {
//     //打开管道文件
//     int fd = open(Path, O_WRONLY);
//     if(fd == -1)
//     {
//         cout << "use write open pipe file fail" << endl;
//         cerr << "errno : " << errno << ", strerror : " << strerror(errno) << endl;
//         exit(-1);
//     }
//     cout << "write open pipe file success" << endl;

//     //开始写入
//     string buffer;
//     while(true)
//     {

//         cout << "write message: ";
//         getline(cin, buffer);

//         if(buffer == "quit")
//             break;

//         ssize_t n = write(fd, buffer.c_str(), buffer.size());

//         if(n == -1)
//         {
//             cout << "write pipe file fail" << endl;
//             cerr << "errno : " << errno << ", strerror : " << strerror(errno) << endl;
//             exit(-1);
//         }

//     }
//     close(fd);
//     return 0;
// }.PHONY:all
// all:file_write file_read
// file_write:file_write.cc
// 	g++ -o $@ $^ -std=c++11 -g
// file_read:file_read.cc
// 	g++ -o $@ $^ -std=c++11 -g
// .PHONY:clean
// clean:
// 	rm -rf file_read file_write#include "pipe.hpp"
// #pragma once
// #include <sys/ipc.h>
// #include <sys/shm.h>

// #define PATHNAME "/home/wyd/git/linux-testing-repository/vscode/shm_ipc"
// #define PROJ_ID 0x8888
// #define SIZE 4096 //这里要传入4096的整数倍，防止空间浪费

// enum Error
// {
//     GetKeyError = 1,
//     GetShmError,
//     CreatShmError,
//     DelShmError,
//     BuildMapError,
//     DelMapError
// };

// //获取key
// key_t GetKey(const char* pathname, int proj_id)
// {
//     key_t ret = ftok(pathname, proj_id);
//     if(ret == -1)
//     {
//         std::cout << "GetKey error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
//         exit(GetKeyError);
//     }
//     return ret;
// }

// //获取共享内存shm
// int GetShm(key_t key)
// {
//     int shmid = shmget(key, SIZE, IPC_CREAT);
//     if(shmid == -1)
//     {
//         std::cout << "GetShm error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
//         exit(GetShmError);
//     }
//     return shmid;
// }

// //创建共享内存shm
// int CreatShm(key_t key, size_t size)
// {
//     int shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666);
//     if(shmid == -1)
//     {
//         std::cout << "CreatShm error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
//         exit(CreatShmError);
//     }
//     return shmid;
// }

// //删除共享内存
// void DelShm(int shmid)
// {
//     int ret = shmctl(shmid, IPC_RMID, nullptr);
//     if(ret == -1)
//     {
//         std::cout << "DelShm error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
//         exit(DelShmError);
//     }
// }

// //建立共享内存与地址空间中的共享区的映射关系
// char* BuildMap(int shmid)
// {
//     char* ret = (char*)shmat(shmid, nullptr, 0);
//     if((int)(*ret) == -1)
//     {
//         std::cout << "BuildMap error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
//         exit(BuildMapError);
//     }
//     return ret;
// }

// //删除映射关系
// void DelMap(const char* pshm)
// {
//     int ret = shmdt((const void*)pshm);
//     if(ret == -1)
//     {
//         std::cout << "DelMap error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
//         exit(DelMapError);
//     }
// }

// //读取共享内存的数据
// void ReadShm(char*& pshm)
// {
//     //创建管道文件
//     Fifo::CreatPipeFile();
//     //读打开管道文件
//     int rfd = Fifo::open_pipe(O_RDONLY);
//     while(true)
//     {
//         if(!Fifo::read_pipe(rfd)) break;
//         std::cout <<  "Message: " << pshm << std::endl;
//         //读管道文件,读到管道文件末尾结束
//         sleep(1);
//     }
//     Fifo::DelPipeFile();
// }

// //写入共享内存的数据
// void WriteShm(char*& pshm)
// {
//     //写打开管道文件
//     int wfd = Fifo::open_pipe(O_WRONLY);
//     for(int i = 'A'; i <= 'Z'; ++i)
//     {
//         pshm[i - 'A'] = i;
//         //写入管道文件
//         Fifo::write_pipe(wfd);
//         sleep(1);
//     }
//     //不写了，且关闭
//     close(wfd);
// }.PHONY:all
// all:ShmClient ShmServer
// ShmClient:ShmClient.cc
// 	g++ -o $@ $^ -std=c++11 -g
// ShmServer:ShmServer.cc
// 	g++ -o $@ $^ -std=c++11 -g
// .PHONY:clean
// clean:
// 	rm -rf ShmClient ShmServer#pragma once
// #include <cstdio>
// #include <iostream>
// #include <string>
// #include <cstring>
// #include <cerrno>
// #include <sys/types.h>
// #include <sys/stat.h>
// #include <fcntl.h>
// #include <unistd.h>
// #define Path "./fifo"
// #define Mode 0666
// //希望这个类帮助我们来完成创建管道文件
// struct Fifo
// {
//     static void CreatPipeFile()
//     {
//         umask(0);
//         int n = mkfifo(Path, Mode);
//         if(n == -1)
//         {
//             std::cout << "create pipe file fail" << std::endl;
//             std::cerr << "errno : " << errno << ", strerror : " << strerror(errno) << std::endl;
//             exit(-1);
//         }
//     }

//     static void DelPipeFile()
//     {
//         unlink(Path);
//     }

//     static bool read_pipe(int rfd)
//     {
//         char c = 0;
//         ssize_t ret = read(rfd, &c, sizeof(c));
//         if(ret == -1)
//         {
//             std::cout << "read pipe file fail" << std::endl;
//             std::cerr << "errno : " << errno << ", strerror : " << strerror(errno) << std::endl;
//             exit(-1);
//         }
//         else if(ret == 0)
//         {
//             return false;
//         }
//         return true;
//     }

//     static void write_pipe(int wfd)
//     {
//         char c = 0;
//         ssize_t ret = write(wfd, &c, sizeof(c));
//         if(ret == -1)
//         {
//             std::cout << "write pipe file fail" << std::endl;
//             std::cerr << "errno : " << errno << ", strerror : " << strerror(errno) << std::endl;
//             exit(-1);
//         }
//     }

//     static int open_pipe(int flag)
//     {
//         int ret = open(Path, flag);
//         if(ret == -1)
//         {
//             std::cout << "open pipe file fail" << std::endl;
//             std::cerr << "errno : " << errno << ", strerror : " << strerror(errno) << std::endl;
//             exit(-1);
//         }
//         return ret;
//     }
// };//这里一定要保证在Server之后运行
// #include "Comm.hpp"
// int main()
// {
//     //获取key
//     key_t key = GetKey(PATHNAME, PROJ_ID);
//     //获取shmid
//     int w_shmid = GetShm(key);
//     //建立映射关系
//     char* pshm = BuildMap(w_shmid);
//     //向shm中数据
//     WriteShm(pshm);
//     //删除映射关系
//     DelMap(pshm);
//     return 0;
// }#include "pipe.hpp"
// #include "Comm.hpp"
// int main()
// {
//     //获取key
//     key_t key = GetKey(PATHNAME, PROJ_ID);
//     //创建shm
//     int r_shmid = CreatShm(key, SIZE);
//     //建立映射关系
//     char* pshm = BuildMap(r_shmid);
//     //读shm的data
//     ReadShm(pshm);
//     //删除映射关系
//     DelMap(pshm);
//     //删除shm
//     DelShm(r_shmid);
//     return 0;
// }
// class Solution
// {
// public:
//     int jewelleryValue(vector<vector<int>>& frame)
//     {
//         int line = frame.size();
//         int column = frame[0].size();
//         vector<vector<int>> dp(line, vector<int>(column));

//         for(int i = 0; i < line; ++i)
//         {
//             for(int j = 0; j < column; ++j)
//             {
//                 int left = 0, order = 0;
//                 if(i - 1 >= 0)
//                 {
//                     order = dp[i - 1][j];
//                 }
//                 if(j - 1 >= 0)
//                 {
//                     left = dp[i][j - 1];
//                 }
//                 dp[i][j] = frame[i][j] + max(left, order);
//             }
//         }

//         return dp[line - 1][column - 1];
//     }
// };
// class Solution
// {
// public:
//     int minFallingPathSum(vector<vector<int>>& mat)
//     {
//         int line = mat.size();
//         int column = mat[0].size();
//         //创建dp表
//         vector<vector<int>> dp(line, vector<int>(column));
//         //初始化dp表
//         for(int i = 0; i < column; ++i) {dp[0][i] = mat[0][i];}
//         //状态转移方程: dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i - 1][j + 1]) + mat[i][j];
//         for(int i = 1; i < line; ++i)
//         {
//             for(int j = 0; j < column; ++j)
//             {
//                 int left_order = 0xfffffff, order = 0xfffffff, right_order = 0xfffffff;
//                 if(i - 1 >= 0)
//                 {
//                     order = dp[i - 1][j];
//                     if(j - 1 >= 0) left_order = dp[i - 1][j - 1];
//                     if(j + 1 < column) right_order = dp[i - 1][j + 1];
//                 }
//                 dp[i][j] = min(order, min(left_order, right_order)) + mat[i][j];
//             }
//         }

//         //返回值
//         sort(dp[line - 1].begin(), dp[line - 1].end());
//         return dp[line - 1][0];
//     }
// };
// class Solution
// {
// public:
//     int minPathSum(vector<vector<int>>& grid)
//     {
//         int line = grid.size();
//         int column = grid[0].size();
//         //创建dp表
//         vector<vector<int>> dp(line, vector<int>(column));
//         //初始化
//         dp[0][0] = grid[0][0];
//         for(int i = 1; i < column; ++i)
//         {
//             dp[0][i] = grid[0][i] + dp[0][i - 1];
//         }
//         //状态转移方程: dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
//         for(int i = 1; i < line; ++i)
//         {
//             for(int j = 0; j < column; ++j)
//             {
//                 int left = 0xfffffff, order = 0xfffffff;
//                 if(i - 1 >= 0) order = dp[i - 1][j];
//                 if(j - 1 >= 0) left = dp[i][j - 1];
//                 dp[i][j] = min(left, order) + grid[i][j];
//             }
//         }

//         return dp[line - 1][column - 1];
//     }
// };
// class Solution
// {
// public:
//     void dfs(vector<int>& A, vector<int>& B, vector<int>& C, int size)
//     {
//         if(size == 1)
//         {
//             C.push_back(A.back());
//             A.pop_back();
//             return;
//         }
//         dfs(A, C, B, size - 1);
//         C.push_back(A.back());
//         A.pop_back();
//         dfs(B, A, C, size - 1);
//     }
//     void hanota(vector<int>& A, vector<int>& B, vector<int>& C)
//     {
//         dfs(A, B ,C, A.size());
//     }
// };
// class Solution
// {
// public:
//     void _reverseList(ListNode* head, ListNode* root)
//     {
//         if(root == nullptr)
//             return;
//         ListNode* cur = root->next;
//         root->next = head->next;
//         head->next = root;
//         _reverseList(head, cur);
//     }
//     ListNode* reverseList(ListNode* head)
//     {
//         ListNode* newhead = new ListNode;
//         _reverseList(newhead, head);
//         return newhead->next;
//     }
// };
// /**
//  * Definition for singly-linked list.
//  * struct ListNode {
//  *     int val;
//  *     ListNode *next;
//  *     ListNode() : val(0), next(nullptr) {}
//  *     ListNode(int x) : val(x), next(nullptr) {}
//  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
//  * };
//  */
// class Solution
// {
// public:
//     void _swapPairs(ListNode* head, ListNode* first, ListNode* second)
//     {
//         if(first == nullptr)
//         {
//             head->next = second;
//             return;
//         }

//         ListNode* f = first;
//         ListNode* s = second;
//         second = f->next;
//         if(second) first = second->next;
//         else first = nullptr;

//         head->next = f;
//         f->next = s;
//         s->next = nullptr;
//         head = s;

//         _swapPairs(head, first, second);
//     }
//     ListNode* swapPairs(ListNode* head)
//     {
//         if(head == nullptr)
//             return nullptr;

//         ListNode* newhead = new ListNode;
//         _swapPairs(newhead, head->next, head);
//         return newhead->next;
//     }
// };
// class Solution
// {
// public:
//     double  _myPow(double x, long long n)
//     {
//         if(n == 0) return 1;
//         if(n == 1) return x;
//         double ret = _myPow(x, n / 3);
//         ret = ret * ret * ret;
//         int dif = n % 3;
//         while(dif--) ret *= x;
//         return ret;
//     }

//     double myPow(double x, long long n)
//     {
//         //x == 0
//         if(x == (double)0) {return 0;}
//         //x != 0 , n == 0
//         if(n == 0 && x != (double)0) {return 1;}

//         //x != 0 , n > 0
//         if(x != (double)0 && n > 0)
//         {
//             return _myPow(x, n);
//             // double total = x;
//             // long long count = 1;
//             // while(count < n)
//             // {
//             //     total *= total;
//             //     count *= 2;
//             // }
//             // int dif = count - n;
//             // while(dif--) {total /= x;}
//             // return total;
//         }

//         //x != 0 , n < 0
//         if(x != (double)0 && n < 0)
//         {
//             return _myPow(1 / x, -n);
//             // double total = x;
//             // long long count = 1;
//             // while(count < abs(n))
//             // {
//             //     total *= total;
//             //     count *= 2;
//             // }
//             // int dif = count - abs(n);
//             // while(dif--) {total /= x;}
//             // return 1 / total;
//         }
//         return 0;
//     }
// };
// #include <vector>
// #include <iostream>
// #include <map>
// using namespace std;
// vector<int> twoSum(vector<int>& nums, int target)
//     {
//         multimap<int, int> umap;
//         for(int i = 0; i < nums.size(); ++i)
//         {
//             umap.insert(make_pair(nums[i], i));
//         }
//         umap.insert(make_pair(target, -1));
//         auto cur = umap.begin();

//         while(cur->first != target)
//         {
//             auto next = ++cur;
//             while(next->first != target)
//             {
//                 if(cur->first + next->first == target)
//                 {
//                     return vector<int>{cur->second, next->second};
//                 }
//                 ++next;
//             }
//             ++cur;
//         }
//         return vector<int>();
//     }
// int main()
// {
//     vector<int> a{2, 7, 11, 5};
//     twoSum(a, 9);
//     return 0;
// }

// #include <iostream>
// #include <unistd.h>
// #include <pthread.h>

// // 全局的，属于各个线程共享的资源，其相关接口的操作都是原子性的
// pthread_cond_t cond = PTHREAD_COND_INITIALIZER;    // 定义全局的cond
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 定义全局的锁
// int ticket = 1000;
// void *function(void *args)
// {
//     std::string name = static_cast<const char *>(args);
//     while (true)
//     {
//         pthread_mutex_lock(&mutex);
//         // 有票
//         if (ticket > 0)
//         {
//             std::cout << name << ", get a ticket : " << ticket-- << std::endl;
//         }
//         // 没票
//         else
//         {
//             // 没有票，就去排队等待
//             std::cout << name << ", 没有票了" << std:: endl;
//             pthread_cond_wait(&cond, &mutex);
//             std::cout << name << "唤醒了" << std:: endl;
//         }
//         pthread_mutex_unlock(&mutex);
//         usleep(1000);
//     }
//     return nullptr;
// }
// int main()
// {
//     pthread_t t1;
//     pthread_create(&t1, nullptr, function, (void *)"thread-1");

//     pthread_t t2;
//     pthread_create(&t2, nullptr, function, (void *)"thread-2");

//     pthread_t t3;
//     pthread_create(&t3, nullptr, function, (void *)"thread-3");

//     // 主线程
//     while (true)
//     {
//         sleep(5);
//         pthread_mutex_lock(&mutex);
//         // std::cout << "main get mutex" << std::endl;
//         if (ticket == 0)
//         {
//             ticket = 1000;
//             pthread_cond_signal(&cond);
//             // pthread_cond_broadcast(&cond);
//         }
//         pthread_mutex_unlock(&mutex);
//     }

//     pthread_join(t1, nullptr);
//     pthread_join(t2, nullptr);
//     pthread_join(t3, nullptr);
//     return 0;
// }#pragma once
// #include <pthread.h>
// #include <iostream>
// #include <string>
// //本hpp作用是封装一下锁,让锁可以自动加锁和解锁，和 smart pointer一个设计理念

// class ProtectResourse
// {
// public:
//     ProtectResourse(pthread_mutex_t* pmutex)
//         : _pmutex(pmutex)
//     {
//         pthread_mutex_lock(_pmutex);
//     }
//     ~ProtectResourse()
//     {
//         pthread_mutex_unlock(_pmutex);
//     }
// private:
//     pthread_mutex_t* _pmutex;
// };#include <pthread.h>
// #include <ctime>
// #include <unistd.h>
// #include <sys/types.h>
// #include <cstdlib>
// #include <cstring>
// #include "QueueBlock.hpp"
// #include "Task.hpp"
// //productor todo
// void* Productor(void* args)
// {
//     const char str[] = "+-*/%!#";
//     QueueBlock<Task<int>>* que = static_cast<QueueBlock<Task<int>>*>(args);
//     while(true)
//     {
//         int data1 = rand() % 10;
//         int data2 = rand() % 10;
//         char ch = str[rand() % strlen(str)];
//         Task<int> t{data1, data2, ch};
//         que->Push(t);
//         std::cout << "I send a task : "
//         << data1 << ch << data2
//         << "=?" << std::endl;
//         usleep(100);
//     }
// }

// //consumer todo
// void* Consumer(void* args)
// {
//     QueueBlock<Task<int>>* que = static_cast<QueueBlock<Task<int>>*>(args);
//     while(true)
//     {
//         Task<int> t;
//         que->Pop(&t);
//         t.Run();
//         std::cout << "I get a task : "
//         << t._data1 << t._rule << t._data2 << "=" << t._result
//         << "[" << t._rerrno << "]" << std::endl;
//     }
// }

// int main()
// {
//     srand(time(nullptr) ^ getpid() ^ pthread_self() ^ getppid());
//     //定义阻塞队列
//     QueueBlock<Task<int>>* que = new QueueBlock<Task<int>>;

//     //创建生产者thread
//     pthread_t productor;
//     pthread_create(&productor, nullptr, Productor, que);

//     //创建消费者thread
//     pthread_t consumer;
//     pthread_create(&consumer, nullptr, Consumer, que);

//     //等待生产者、消费者
//     pthread_join(productor, nullptr);
//     pthread_join(consumer, nullptr);
//     return 0;
// }Exe:main.cc
// 	g++ -o $@ $^ -std=c++11 -lpthread
// .PHONY:clean
// clean:
// 	rm -rf Exe
// //此hpp用于形成  单生产者消费者模型 中的交易区域，这里使用阻塞队列来完成
// #pragma once
// #include <iostream>
// #include <queue>
// #include <pthread.h>
// #include "lockProtect.hpp"
// //最大容量
// #define MAX_CAPACITY 5
// //使用模版，让资源可以是任意类型，包括class/strcut类、函数等
// template <class T>
// class QueueBlock
// {
// public:
//     ////////////////////////////////////////////////////////////
//     // 这里设计成员有mutex、cond的目的是，让外部不必担心线程安全的问题 //
//     // 所以构造函数和析构函数这里就要自动初始化和销毁mutex、cond      //
//     ////////////////////////////////////////////////////////////

//     //构造函数
//     QueueBlock(int capacity = MAX_CAPACITY)
//         :_capacity(capacity)
//     {
//         pthread_mutex_init(&_mutex, nullptr);
//         pthread_cond_init(&_p_cond, nullptr);
//         pthread_cond_init(&_c_cond, nullptr);
//     }

//     //析构函数
//     ~QueueBlock()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_p_cond);
//         pthread_cond_destroy(&_c_cond);
//     }

//     //生产资源，已经涉及到共享资源的访问，所以要加锁解锁
//     void Push(T& data)
//     {
//         ProtectResourse protect(&_mutex);
//         // pthread_mutex_lock(&_mutex);
//         {
//             // if(IsFull())
//             while(IsFull()) //这里使用while，是怕一次唤醒多个线程，有伪唤醒，导致满了还生产
//             {
//                 pthread_cond_wait(&_p_cond, &_mutex);
//             }

//             _q.push(data);
//             pthread_cond_signal(&_c_cond);
//         }
//         // pthread_mutex_unlock(&_mutex);
//     }

//     //消费资源，也会涉及到共享资源的访问，所以也要加锁解锁
//     void Pop(T* data)
//     {
//         ProtectResourse protect(&_mutex);
//         // pthread_mutex_lock(&_mutex);
//         {
//             // if(IsEmpty())
//             while(IsEmpty()) //这里使用while，是因为一次唤醒多个线程，有伪唤醒，导致没有resourse还访问
//             {
//                 pthread_cond_wait(&_c_cond, &_mutex);
//             }

//             *data = _q.front();
//             _q.pop();
//             pthread_cond_signal(&_p_cond);
//         }
//         // pthread_mutex_unlock(&_mutex);

//     }

//     //判断资源是否已经满了
//     bool IsFull()
//     {
//         return _q.size() == _capacity;
//     }

//     //判断是否资源为空
//     bool IsEmpty()
//     {
//         return _q.size() == 0;
//     }

// private:
//     std::queue<T> _q;             //阻塞队列
//     int _capacity;           //队列的最大容量
//     pthread_mutex_t _mutex;   //互斥锁
//     pthread_cond_t _p_cond;  //给procductor的条件变量，让consumer控制
//     pthread_cond_t _c_cond;  //给consumer的条件变量，让productor控制
// };#pragma once
// //本Task.hpp 用来派发任务，
// //我们可以设计各种类型的任务，来让生产者传到阻塞队列中，
// //再让消费者在其中获取

// //简单设计一个 “自动计算器”//
// enum ReErrno
// {
//     Correct,
//     Zero,
//     Unknown
// };
// template<class T>
// class Task
// {
// public:
//     Task()
//     {}
//     Task(T data1, T data2, char rule)
//         : _data1(data1)
//         , _data2(data2)
//         , _rule(rule)
//         , _result(0)
//         , _rerrno(Correct)
//     {}
//     ~Task()
//     {}
//     void Run()
//     {
//         switch (_rule)
//         {
//             case '+':
//                 _result = _data1 + _data2;
//                 break;
//             case '-':
//                 _result = _data1 - _data2;
//                 break;
//             case '*':
//                 _result = _data1 * _data2;
//                 break;
//             case '/':
//             {
//                 if(_data2 == 0)
//                 {
//                     _rerrno = Zero;
//                 }
//                 _result = _data1 / _data2;
//             }
//                 break;
//             case '%':
//             {
//                 if(_data2 == 0)
//                 {
//                     _rerrno = Zero;
//                 }
//                 _result = _data1 % _data2;
//             }
//                 break;
//             default:
//                 _rerrno = Unknown;
//                 break;
//         }
//     }
//     void operator*(Task<T> task)
//     {
//         _data1 = task._data1;
//         _data2 = task._data2;
//         _rule = task._rule;
//         _result = task._result;
//         _rerrno = task._rerrno;
//     }

// public:
//     T _data1;
//     T _data2;
//     char _rule;
//     T _result;
//     int _rerrno;
// };
// class Solution
// {
// public:
//     string longestCommonPrefix(vector<string>& strs)
//     {
//         string target = strs[0];
//         for(int i = 1; i < strs.size(); ++i)
//         {
//             int cur = 0, next = 0;
//             string new_target;
//             while(strs[i - 1][cur] || strs[i][next])
//             {
//                 if(strs[i - 1][cur]
//                     && strs[i][next]
//                     && (strs[i - 1][cur] == strs[i][next]))
//                 {
//                     new_target += strs[i - 1][cur];
//                     ++cur;
//                     ++next;
//                 }
//                 else
//                 {
//                     if(target.size() > new_target.size())
//                         target = new_target;
//                     break;
//                 }
//             }
//         }
//         return target;
//     }
// };
// class Solution
// {
// public:
//     int massage(vector<int>& nums)
//     {
//         if(nums.size() == 0) return 0;
//         //创建dp表
//         vector<int> dp(nums.size() + 1);
//         //初始化dp表
//         dp[0] = 0; dp[1] = nums[0];
//         for(int i = 2; i < dp.size(); ++i)
//             dp[i] = max(dp[i - 2] + nums[i - 1], dp[i - 1]);
//         return dp[nums.size()];
//     }
// };
// class Solution
// {
// public:
//     string removeDuplicates(string s)
//     {
//         stack<char> ch_stack;
//         for(int i = 0; i < s.size(); ++i)
//         {
//             if(!ch_stack.empty())
//             {
//                 if(s[i] == ch_stack.top())   ch_stack.pop();
//                 else ch_stack.push(s[i]);
//             }
//             else ch_stack.push(s[i]);
//         }
//         string ret;
//         while(!ch_stack.empty())
//         {
//             ret += ch_stack.top();
//             ch_stack.pop();
//         }
//         reverse(ret.begin(), ret.end());
//         return ret;
//     }
// };
// #include "Log.hpp"
// int main()
// {
//     Log log;
//     log.LogMessage(OneFile, Debug, "this is a debug message %d-%f\n", 666, 3.14);
//     log.LogMessage(ClassFile, Debug, "this is a debug message %d-%f\n", 666, 3.14);
//     log.LogMessage(ClassFile, Warning, "this is a debug message %d-%f\n", 666, 3.14);
//     log.LogMessage(ClassFile, Error, "this is a debug message %d-%f\n", 666, 3.14);
//     log.LogMessage(ClassFile, Info, "this is a debug message %d-%f\n", 666, 3.14);
//     return 0;
// }//本hpp用于输出我们日常测试函数的信息，比如一些错误信息，调试信息等\
// 写入到显示器或文件中，具体看我们想如何实现

// #pragma once
// #include <ctime>
// #include <unistd.h>
// #include <pthread.h>
// #include <iostream>
// #include <string>
// #include <sys/types.h>
// #include <sys/stat.h>
// #include <fcntl.h>
// #include <stdarg.h>
// // 日志等级类别
// enum Level
// {
//     Info,    // 正常
//     Debug,   // 测试
//     Warning, // 警告
//     Error    // 错误
// };
// enum Mode
// {
//     DisPlay,  // 显示器
//     OneFile,  // 一个文件
//     ClassFile // 多种类型文件
// };
// class Log
// {
// public:
//     void LogMessage(int mode, int level, const char *format, ...)
//     {
//         _level = level;
//         _mode = mode;

//         // 定义一个缓冲区，用于接收日志信息，最后分模式写入对应的文件
//         char rignt[1024];
//         // 定义可变参数列表
//         va_list args;
//         // 初始化可变参数列表,这一步是通过前一个参数的地址将可变参数列表中的各个参数都找到
//         va_start(args, format);
//         vsnprintf(rignt, sizeof(rignt), format, args);

//         //现今buffer中就是日志的内容，但是我们将其组合成理想格式\
//         ##level##[time][pid] : message
//         std::string left = Get_Left_Message();

//         std::string message = left;
//         message += " : ";
//         message += rignt;
//         Print_Mode(message);
//     }

// private:
//     time_t _time;        // 输出日志信息时的当地时间戳
//     std::string _matter; // 输出的内容
//     int _level;          // 日志等级
//     int _mode;           // 输出的模式：显示器或文件输出
//     pthread_t _tid;      // 线程tid

//     void Print_Mode(std::string &message)
//     {
//         switch (_mode)
//         {
//         case DisPlay:
//         {
//             printf("%s", message.c_str());
//         }
//         break;
//         case OneFile:
//         {
//             Print_OneFile(message);
//         }
//         break;
//         case ClassFile:
//         {
//             Print_ClassFile(message);
//         }
//         break;
//         default:
//             printf("unknow mode ,error\n");
//             break;
//         }
//     }

//     void Print_OneFile(std::string &message)
//     {
//         //建立统一目录
//         std::string dirname = "Log";
//         mkdir(dirname.c_str(), 0775);

//         umask(0);
//         std::string filename = "./Log/log.";
//         if (_mode == OneFile)
//         {
//             filename += "all";
//         }
//         else
//         {
//             switch (_level)
//             {
//             case Info:
//                 filename += "info";
//                 break;
//             case Debug:
//                 filename += "debug";
//                 break;
//             case Warning:
//                 filename += "warning";
//                 break;
//             case Error:
//                 filename += "error";
//                 break;
//             default:
//                 filename += "unknow";
//                 break;
//             }
//         }
//         int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
//         write(fd, message.c_str(), message.size());
//         close(fd);
//     }

//     void Print_ClassFile(std::string &message)
//     {
//         Print_OneFile(message);
//     }

//     std::string Get_Left_Message()
//     {
//         char left_message[1024];
//         snprintf(left_message, sizeof(left_message),
//                  "[%s][%s][%s]",
//                  Get_Level().c_str(),
//                  Get_Local_Time().c_str(),
//                  Get_Tid().c_str());
//         return left_message;
//     }

//     std::string Get_Local_Time()
//     {
//         // 先获取时间戳
//         _time = time(nullptr);
//         // 将时间戳转换为当地时间
//         tm *LocalTime = localtime(&_time);
//         std::string local_time;

//         local_time += std::to_string(LocalTime->tm_year + 1900);
//         local_time += '-';

//         local_time += std::to_string(LocalTime->tm_mon + 1);
//         local_time += '-';

//         local_time += std::to_string(LocalTime->tm_mday);
//         local_time += ' ';

//         local_time += std::to_string(LocalTime->tm_hour);
//         local_time += ':';

//         local_time += std::to_string(LocalTime->tm_min);
//         local_time += ':';

//         local_time += std::to_string(LocalTime->tm_sec);
//         return local_time;
//     }

//     std::string Get_Tid()
//     {
//         return std::to_string((long long)pthread_self());
//     }

//     std::string Get_Level()
//     {
//         std::string slevel;
//         switch (_level)
//         {
//         case Info:
//             slevel = "Info";
//             break;
//         case Debug:
//             slevel = "Debug";
//             break;
//         case Warning:
//             slevel = "Warning";
//             break;
//         case Error:
//             slevel = "Error";
//             break;
//         default:
//             slevel = "UnKnow";
//             break;
//         }
//         return slevel;
//     }
// };#include <iostream>
// #include <pthread.h>
// #include <unistd.h>
// #include <ctime>
// #include <cstring>
// #include <cstdlib>
// #include "threadpool.hpp"
// #include "Task.hpp"
// const char rules[] = "+-*/%";
// void Push_Task(ThreadPool<Task<int>> &threads)
// {
//     // int count = 9;
//     while (true)
//     {
//         sleep(1);
//         int data1 = rand() % 10;
//         int data2 = rand() % 10;
//         char rule = rules[rand() % strlen(rules)];
//         Task<int> task{data1, data2, rule};
//         threads.Push(task);
//     }
// }
// int main()
// {
//     srand(time(nullptr) ^ pthread_self()); // 目的仅是让种子更随机一点
//     // 定义一个线程池
//     ThreadPool<Task<int>> threads;
//     // 让新线程开始运行
//     threads.Start_Task();

//     // 主线程派发任务
//     Push_Task(threads);

//     // 主线程回收新线程
//     threads.Join_Threads();
//     return 0;
// }

// // long long function(int arg)
// // {
// //     while(arg)
// //     {
// //         std::cout << arg-- << std::endl;
// //         sleep(1);
// //     }
// //     return 10000;
// // }
// // int main()
// // {
// //     Thread<long long, int> thread1(function, 3);
// //     std::cout << thread1.thread_name() << "is running" << std::endl;
// //     thread1.Start();
// //     thread1.Join();

// //     Thread<long long, int> thread2(function, 5);
// //     std::cout << thread2.thread_name() << "is running" << std::endl;
// //     thread2.Start();
// //     thread2.Join();
// //     return 0;
// // }
// // #include <unistd.h>
// // #include "threadpool.hpp"

// // int main()
// // {
// //     ThreadPool<int> thread_pool;
// //     thread_pool.Start();
// //     int i = 0;
// //     while(true)
// //     {
// //         sleep(5);
// //         thread_pool.Push(i++);
// //     }
// //     thread_pool.Join();
// //     return 0;
// // }
// // #include <iostream>
// // #include <unistd.h>
// // #include <ctime>
// // #include <cstdlib>
// // #include <cstring>
// // #include "ProtectResourse.hpp"
// // #include "threadpool.hpp"
// // #include "RingBuffer.hpp"
// // #include "Task.hpp"
// // //生产者方法
// // const char str[] = "+-*/%!@";
// // void* Productor(void* arg)
// // {
// //     Productor_C<Task<int>>* PD  = static_cast<Productor_C<Task<int>>*>(arg);
// //     std::string name = PD->GetName();
// //     while(true)
// //     {
// //         //生产数据
// //         int data1 = rand() % 10;
// //         int data2 = rand() % 10;
// //         char oper = str[rand() % strlen(str)];
// //         Task<int> task{data1, data2, oper};

// //         //插入
// //         PD->_RB->Push(task);

// //         //打印日志
// //         std::cout << name << " : ";
// //         task.TaskPrint();

// //     }
// // }

// // //消费者方法
// // void* Consumer(void* arg)
// // {
// //     Consumer_C<Task<int>>* CS = static_cast<Consumer_C<Task<int>>*>(arg);
// //     std::string name = CS->GetName();
// //     while(true)
// //     {
// //         //拿数据
// //         Task<int> task;
// //         CS->_RB->Pop(&task);

// //         //处理数据
// //         task.Run();

// //         //打印日志
// //         std::cout << name << " : ";
// //         task.ResultPrint();
// //         sleep(1);
// //     }

// // }
// // int main()
// // {
// //     srand(time(nullptr) ^ pthread_self());
// //     //创建两个生产者
// //     threadpool procductors(2);
// //     //创建三个消费者
// //     threadpool consumers(3);
// //     //定义一份shared resourse 环形队列
// //     RingBuffer<Task<int>>* RB = new RingBuffer<Task<int>>;
// //     Productor_C<Task<int>> PD(RB);
// //     Consumer_C<Task<int>> CS(RB);
// //     //让新线程执行对应方法
// //     procductors.Create(Productor, &PD);
// //     consumers.Create(Consumer, &CS);
// //     //等待新线程
// //     procductors.Join();
// //     consumers.Join();
// //     return 0;
// // }threadpool:main.cc
// 	g++ -o $@ $^ -std=c++11 -lpthread
// .PHONY:clean
// clean:
// 	rm -rf threadpool#pragma once
// #include <pthread.h>
// #include <iostream>
// #include <string>
// //本hpp作用是封装一下锁,让锁可以自动加锁和解锁，和 smart pointer一个设计理念

// class ProtectResourse
// {
// public:
//     ProtectResourse(pthread_mutex_t* pmutex)
//         : _pmutex(pmutex)
//     {
//         pthread_mutex_lock(_pmutex);
//     }
//     ~ProtectResourse()
//     {
//         pthread_mutex_unlock(_pmutex);
//     }
// private:
//     pthread_mutex_t* _pmutex;
// };//本Task.hpp 用来设计任务，在此仅简单设计一个 “自动计算器”
// #pragma once
// enum ReErrno
// {
//     Correct,
//     Zero,
//     Unknown
// };

// template<class T>
// class Task
// {
// public:
//     Task()
//     {}
//     Task(T data1, T data2, char rule)  
//         : _data1(data1)
//         , _data2(data2)
//         , _rule(rule)
//         , _result(0)
//         , _rerrno(Correct)
//     {}
//     ~Task()
//     {}

//     //处理任务，这里是给我们拿出任务的线程执行
//     void Run()
//     {
//         switch (_rule)
//         {
//             case '+':
//                 _result = _data1 + _data2;
//                 break;
//             case '-':
//                 _result = _data1 - _data2;
//                 break;
//             case '*':
//                 _result = _data1 * _data2;
//                 break;
//             case '/':
//             {
//                 if(_data2 == 0)
//                 {
//                     _rerrno = Zero;
//                 }
//                 _result = _data1 / _data2;
//             }
//                 break;
//             case '%':
//             {
//                 if(_data2 == 0)
//                 {
//                     _rerrno = Zero;
//                 }
//                 _result = _data1 % _data2;
//             }
//                 break;
//             default:
//                 _rerrno = Unknown;
//                 break;
//         }
//     }
//     void operator*(Task<T> task)
//     {
//         _data1 = task._data1;
//         _data2 = task._data2;
//         _rule = task._rule;
//         _result = task._result;
//         _rerrno = task._rerrno;
//     }
    
//     std::string TaskPrint()
//     {
//         char buffer[1024];
//         snprintf(buffer, sizeof(buffer),  "%d %c %d = ?", _data1, _rule, _data2);
//         return buffer;   
//     }

//     std::string ResultPrint()
//     {
//         char buffer[1024];
//         snprintf(buffer, sizeof(buffer), "%d %c %d = %d[%s]", 
//                 _data1, _rule, _data2, _result, Rerrno_To_string().c_str());
//         return buffer;   
//     }

//     std::string Rerrno_To_string()
//     {
//         switch(_rerrno)
//         {
//             case 0:
//                 return "Correct";
//             case 1:
//                 return "Zero";
//             default:
//                 return "Unknown";
//         }
//     }
// private:
//     T _data1;
//     T _data2;
//     char _rule;
//     T _result;
//     int _rerrno;
// 在设计线程池时，我们最主要的两个成员变量为：共享资源和N个新线程\
// 剩下其他的成员变量都是基于这两者来进行增补的\
// 而成员函数主要是 主线程派发任务 和 新线程拿到任务并处理\
// 其他成员函数自行增补
// template <class T>
// class ThreadPool;
// #pragma once
// #include <iostream>
// #include <pthread.h>
// #include <queue>  //用作 共享资源
// #include <vector> //用作 存放线程们
// #include "Threads.hpp"
// #include "ProtectResourse.hpp"
// #include "Log.hpp"
// #define THREADSIZE 5 // 线程组中线程的个数
// // 这里模版给的是共享资源的内容类型，可以派发内置类型，也可以派发自定义类型
// template <class T>
// class ThreadPool
// {
// public:
//     //构造函数【OK】
//     ThreadPool(int size = THREADSIZE)
//         : _thread_size(size)
//     {
//         // 初始化线程组
//         for (int i = 0; i < size; ++i)
//         {
//             _threads.emplace_back
//             (
//                 //////////////////////////////////////////
//                 //////////// 重点 ////////////////////////
//                 std::bind(&ThreadPool<T>::Run, 
//                           this, 
//                           std::placeholders::_1, 
//                           std::placeholders::_2)
//                 , 0
//             );
//         }

//         pthread_mutex_init(&_mutex, nullptr);
//         pthread_cond_init(&_cond, nullptr);
//     }
//     //析构函数【OK】
//     ~ThreadPool()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_cond);
//     }

//     // 主线程派发任务【OK】
//     void Push(T &task)
//     {
//         ProtectResourse protect(&_mutex);
//         {
//             static int i = 0;
//             _shared_resourse.push(task);
//             Log log;
//             log.LogMessage(ClassFile, Debug + i++, 
//                            "main thread push a task : %s\n", task.TaskPrint().c_str());
//             i %= 4;
//             One_Thread_Wakeup();
//         }
//     }
    
//     // 线程组执行任务【OK】
//     void Start_Task()
//     {
//         for (auto &e : _threads)
//         {
//             e.Start();
//         }
//     }

//     // 回收线程组【OK】
//     void Join_Threads()
//     {
//         for (auto &e : _threads)
//         {
//             e.Join();
//         }
//     }

// private:
//     std::queue<T> _shared_resourse;            // 存放任务的共享资源
//     int _thread_size;                          // 线程组中线程的个数
//     std::vector< Thread<void* ,int> > _threads; // 线程组
//     pthread_mutex_t _mutex;                    // 线程组之间互斥访问共享资源的锁
//     pthread_cond_t _cond;                      // 主线程与线程组之间要保持同步&&互斥时使用的条件变量

// ////////////////////////////////////////////////////////////////////////////
//     void *Run(std::string name, int arg)   //重点！！！！！！！
//     {
//         static int i = 0;
//         T task;
//         while (true)
//         {
//             ProtectResourse protect(&_mutex);
//             {
//                 while(_shared_resourse.empty())
//                 {
//                     Thread_Wait();
//                 }

//                 // 拿任务
//                 task = _shared_resourse.front();
//                 _shared_resourse.pop();
//             }
//             // 处理任务
//             task.Run();
//             Log log;
//             log.LogMessage(ClassFile, Debug + i++, 
//                            "%s : %s\n", name.c_str(),  task.ResultPrint().c_str());
//             i %= 4;
//         }
//         return nullptr;
//     }

//     //唤醒一个线程 【OK】
//     void One_Thread_Wakeup()
//     {
//         pthread_cond_signal(&_cond);
//     }
//     //唤醒所有线程 【OK】
//     void All_Thread_Wakeup()
//     {
//         pthread_cond_broadcast(&_cond);
//     }
//     //没有资源了，让线程组等待 【OK】
//     void Thread_Wait()
//     {
//         pthread_cond_wait(&_cond, &_mutex);
//     }
// };// 本hpp用于 <<封装自己的线程相关接口，给线程添加更多属性>> 方便测试查看
// // 可用于学习，不可进行抄袭、转载、更改等对原创知识有害的操作，如需转载分享，请标明出处

// #pragma once
// #include <pthread.h>
// #include <string>
// #include <functional>

// // 形同于：typedef std::function<void*(void*)> func_t
// template <class R, class V>
// using func_t = std::function<R(std::string, V)>;

// template <class R, class V>
// class Thread
// {
// public:
//     Thread(func_t<R, V> func, V arg)
//         : _thread(0)
//         , _thread_name()
//         , _attr(pthread_attr_t())
//         , _istunning(false)
//         , _func(func)
//         , _arg(arg)
//     {
//         _thread_name = Create_Thread_Name();
//     }

//     // 开始让线程执行对应方法
//     void Start()
//     {
//         _istunning = true;
//         // 前两个都为输出型参数，可以得到线程ID与属性集
//         pthread_create(&_thread, &_attr, Function, (void *)this);
//     }

//     // 等待线程
//     void Join()
//     {
//         // 可以得到thread执行完函数方法的返回值信息
//         pthread_join(_thread, &_return_message);
//         _istunning = false;
//     }

//     //拿到线程的成员变量
//     pthread_t tid() {return _thread;}
//     std::string& name() {return _thread_name;}
//     const pthread_attr_t& attr() {return _attr;}
//     bool Isrunning() {return _istunning;}
//     R& re_message() {return reinterpret_cast<R>(_return_message);}

// private:
//     pthread_t _thread;          // 线程ID
//     std::string _thread_name;   // 线程名字 
//     const pthread_attr_t _attr; // 线程属性集
//     bool _istunning;            // 线程是否运行
//     void *_return_message;      // 线程执行完对应方法的返回值信息
//     func_t<R, V> _func;         // 线程执行的函数方法
//     V _arg;                     // 函数方法的参数

//     // 这么写Functuon的原因:我们可以通过伪造一个void*(*)(void*)类型的函数
//     // 但是在函数内部可以用来回调我们在main.cc中的函数方法
//     // 通过第二个参数传this指针，可以找到_func和_arg
//     // 至此可以让我们成功回调我们自定义的函数方法
//     static void *Function(void *arg)
//     {
//         Thread<R, V> *pThread = static_cast<Thread<R, V> *>(arg);
//         return reinterpret_cast<void*>(pThread->_func(pThread->_thread_name, pThread->_arg));
//     }

//     std::string Create_Thread_Name()
//     {
//         std::string name = "thread-";
//         static int i = 1; //定义一个局部的静态变量，作用域是该函数内有效，生命周期为全局的
//         name += std::to_string(i++);
//         return name;
//     }
// };//本hpp用于输出我们日常测试函数的信息，比如一些错误信息，调试信息等\
// 写入到显示器或文件中，具体看我们想如何实现

// #pragma once
// #include <ctime>
// #include <unistd.h>
// #include <pthread.h>
// #include <iostream>
// #include <string>
// #include <sys/types.h>
// #include <sys/stat.h>
// #include <fcntl.h>
// #include <stdarg.h>
// // 日志等级类别
// enum Level
// {
//     Info,    // 正常
//     Debug,   // 测试
//     Warning, // 警告
//     Error    // 错误
// };
// enum Mode
// {
//     DisPlay,  // 显示器
//     OneFile,  // 一个文件
//     ClassFile // 多种类型文件
// };
// class Log
// {
// public:
//     void LogMessage(int mode, int level, const char *format, ...)
//     {
//         _level = level;
//         _mode = mode;

//         // 定义一个缓冲区，用于接收日志信息，最后分模式写入对应的文件
//         char rignt[1024];
//         // 定义可变参数列表
//         va_list args;
//         // 初始化可变参数列表,这一步是通过前一个参数的地址将可变参数列表中的各个参数都找到
//         va_start(args, format);
//         vsnprintf(rignt, sizeof(rignt), format, args);

//         //现今buffer中就是日志的内容，但是我们将其组合成理想格式\
//         ##level##[time][pid] : message
//         std::string left = Get_Left_Message();

//         std::string message = left;
//         message += " : ";
//         message += rignt;
//         Print_Mode(message);
//     }

// private:
//     time_t _time;        // 输出日志信息时的当地时间戳
//     std::string _matter; // 输出的内容
//     int _level;          // 日志等级
//     int _mode;           // 输出的模式：显示器或文件输出
//     pthread_t _tid;      // 线程tid

//     void Print_Mode(std::string &message)
//     {
//         switch (_mode)
//         {
//         case DisPlay:
//         {
//             printf("%s", message.c_str());
//         }
//         break;
//         case OneFile:
//         {
//             Print_OneFile(message);
//         }
//         break;
//         case ClassFile:
//         {
//             Print_ClassFile(message);
//         }
//         break;
//         default:
//             printf("unknow mode ,error\n");
//             break;
//         }
//     }

//     void Print_OneFile(std::string &message)
//     {
//         //建立统一目录
//         std::string dirname = "Log";
//         mkdir(dirname.c_str(), 0775);

//         umask(0);
//         std::string filename = "./Log/log.";
//         if (_mode == OneFile)
//         {
//             filename += "all";
//         }
//         else
//         {
//             switch (_level)
//             {
//             case Info:
//                 filename += "info";
//                 break;
//             case Debug:
//                 filename += "debug";
//                 break;
//             case Warning:
//                 filename += "warning";
//                 break;
//             case Error:
//                 filename += "error";
//                 break;
//             default:
//                 filename += "unknow";
//                 break;
//             }
//         }
//         int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
//         write(fd, message.c_str(), message.size());
//         close(fd);
//     }

//     void Print_ClassFile(std::string &message)
//     {
//         Print_OneFile(message);
//     }

//     std::string Get_Left_Message()
//     {
//         char left_message[1024];
//         snprintf(left_message, sizeof(left_message),
//                  "[%s][%s][%s]",
//                  Get_Level().c_str(),
//                  Get_Local_Time().c_str(),
//                  Get_Tid().c_str());
//         return left_message;
//     }

//     std::string Get_Local_Time()
//     {
//         // 先获取时间戳
//         _time = time(nullptr);
//         // 将时间戳转换为当地时间
//         tm *LocalTime = localtime(&_time);
//         std::string local_time;

//         local_time += std::to_string(LocalTime->tm_year + 1900);
//         local_time += '-';

//         local_time += std::to_string(LocalTime->tm_mon + 1);
//         local_time += '-';

//         local_time += std::to_string(LocalTime->tm_mday);
//         local_time += ' ';

//         local_time += std::to_string(LocalTime->tm_hour);
//         local_time += ':';

//         local_time += std::to_string(LocalTime->tm_min);
//         local_time += ':';

//         local_time += std::to_string(LocalTime->tm_sec);
//         return local_time;
//     }

//     std::string Get_Tid()
//     {
//         return std::to_string((long long)pthread_self());
//     }

//     std::string Get_Level()
//     {
//         std::string slevel;
//         switch (_level)
//         {
//         case Info:
//             slevel = "Info";
//             break;
//         case Debug:
//             slevel = "Debug";
//             break;
//         case Warning:
//             slevel = "Warning";
//             break;
//         case Error:
//             slevel = "Error";
//             break;
//         default:
//             slevel = "UnKnow";
//             break;
//         }
//         return slevel;
//     }
// };#include <iostream>
// #include <pthread.h>
// #include <unistd.h>
// #include <ctime>
// #include <cstring>
// #include <cstdlib>
// #include "threadpool.hpp"
// #include "Task.hpp"
// const char rules[] = "+-*/%";
// void Push_Task(ThreadPool<Task<int>> &threads)
// {
//     // int count = 9;
//     while (true)
//     {
//         sleep(1);
//         int data1 = rand() % 10;
//         int data2 = rand() % 10;
//         char rule = rules[rand() % strlen(rules)];
//         Task<int> task{data1, data2, rule};
//         threads.Push(task);
//     }
// }
// int main()
// {
//     srand(time(nullptr) ^ pthread_self()); // 目的仅是让种子更随机一点
//     // 定义一个线程池
//     ThreadPool<Task<int>> threads;
//     // 让新线程开始运行
//     threads.Start_Task();

//     // 主线程派发任务
//     Push_Task(threads);

//     // 主线程回收新线程
//     threads.Join_Threads();
//     return 0;
// }

// // long long function(int arg)
// // {
// //     while(arg)
// //     {
// //         std::cout << arg-- << std::endl;
// //         sleep(1);
// //     }
// //     return 10000;
// // }
// // int main()
// // {
// //     Thread<long long, int> thread1(function, 3);
// //     std::cout << thread1.thread_name() << "is running" << std::endl;
// //     thread1.Start();
// //     thread1.Join();

// //     Thread<long long, int> thread2(function, 5);
// //     std::cout << thread2.thread_name() << "is running" << std::endl;
// //     thread2.Start();
// //     thread2.Join();
// //     return 0;
// // }
// // #include <unistd.h>
// // #include "threadpool.hpp"

// // int main()
// // {
// //     ThreadPool<int> thread_pool;
// //     thread_pool.Start();
// //     int i = 0;
// //     while(true)
// //     {
// //         sleep(5);
// //         thread_pool.Push(i++);
// //     }
// //     thread_pool.Join();
// //     return 0;
// // }
// // #include <iostream>
// // #include <unistd.h>
// // #include <ctime>
// // #include <cstdlib>
// // #include <cstring>
// // #include "ProtectResourse.hpp"
// // #include "threadpool.hpp"
// // #include "RingBuffer.hpp"
// // #include "Task.hpp"
// // //生产者方法
// // const char str[] = "+-*/%!@";
// // void* Productor(void* arg)
// // {
// //     Productor_C<Task<int>>* PD  = static_cast<Productor_C<Task<int>>*>(arg);
// //     std::string name = PD->GetName();
// //     while(true)
// //     {
// //         //生产数据
// //         int data1 = rand() % 10;
// //         int data2 = rand() % 10;
// //         char oper = str[rand() % strlen(str)];
// //         Task<int> task{data1, data2, oper};

// //         //插入
// //         PD->_RB->Push(task);

// //         //打印日志
// //         std::cout << name << " : ";
// //         task.TaskPrint();

// //     }
// // }

// // //消费者方法
// // void* Consumer(void* arg)
// // {
// //     Consumer_C<Task<int>>* CS = static_cast<Consumer_C<Task<int>>*>(arg);
// //     std::string name = CS->GetName();
// //     while(true)
// //     {
// //         //拿数据
// //         Task<int> task;
// //         CS->_RB->Pop(&task);

// //         //处理数据
// //         task.Run();

// //         //打印日志
// //         std::cout << name << " : ";
// //         task.ResultPrint();
// //         sleep(1);
// //     }

// // }
// // int main()
// // {
// //     srand(time(nullptr) ^ pthread_self());
// //     //创建两个生产者
// //     threadpool procductors(2);
// //     //创建三个消费者
// //     threadpool consumers(3);
// //     //定义一份shared resourse 环形队列
// //     RingBuffer<Task<int>>* RB = new RingBuffer<Task<int>>;
// //     Productor_C<Task<int>> PD(RB);
// //     Consumer_C<Task<int>> CS(RB);
// //     //让新线程执行对应方法
// //     procductors.Create(Productor, &PD);
// //     consumers.Create(Consumer, &CS);
// //     //等待新线程
// //     procductors.Join();
// //     consumers.Join();
// //     return 0;
// // }threadpool:main.cc
// 	g++ -o $@ $^ -std=c++11 -lpthread
// .PHONY:clean
// clean:
// 	rm -rf threadpool#pragma once
// #include <pthread.h>
// #include <iostream>
// #include <string>
// //本hpp作用是封装一下锁,让锁可以自动加锁和解锁，和 smart pointer一个设计理念

// class ProtectResourse
// {
// public:
//     ProtectResourse(pthread_mutex_t* pmutex)
//         : _pmutex(pmutex)
//     {
//         pthread_mutex_lock(_pmutex);
//     }
//     ~ProtectResourse()
//     {
//         pthread_mutex_unlock(_pmutex);
//     }
// private:
//     pthread_mutex_t* _pmutex;
// };//本Task.hpp 用来设计任务，在此仅简单设计一个 “自动计算器”
// #pragma once
// enum ReErrno
// {
//     Correct,
//     Zero,
//     Unknown
// };

// template<class T>
// class Task
// {
// public:
//     Task()
//     {}
//     Task(T data1, T data2, char rule)  
//         : _data1(data1)
//         , _data2(data2)
//         , _rule(rule)
//         , _result(0)
//         , _rerrno(Correct)
//     {}
//     ~Task()
//     {}

//     //处理任务，这里是给我们拿出任务的线程执行
//     void Run()
//     {
//         switch (_rule)
//         {
//             case '+':
//                 _result = _data1 + _data2;
//                 break;
//             case '-':
//                 _result = _data1 - _data2;
//                 break;
//             case '*':
//                 _result = _data1 * _data2;
//                 break;
//             case '/':
//             {
//                 if(_data2 == 0)
//                 {
//                     _rerrno = Zero;
//                 }
//                 _result = _data1 / _data2;
//             }
//                 break;
//             case '%':
//             {
//                 if(_data2 == 0)
//                 {
//                     _rerrno = Zero;
//                 }
//                 _result = _data1 % _data2;
//             }
//                 break;
//             default:
//                 _rerrno = Unknown;
//                 break;
//         }
//     }
//     void operator*(Task<T> task)
//     {
//         _data1 = task._data1;
//         _data2 = task._data2;
//         _rule = task._rule;
//         _result = task._result;
//         _rerrno = task._rerrno;
//     }
    
//     std::string TaskPrint()
//     {
//         char buffer[1024];
//         snprintf(buffer, sizeof(buffer),  "%d %c %d = ?", _data1, _rule, _data2);
//         return buffer;   
//     }

//     std::string ResultPrint()
//     {
//         char buffer[1024];
//         snprintf(buffer, sizeof(buffer), "%d %c %d = %d[%s]", 
//                 _data1, _rule, _data2, _result, Rerrno_To_string().c_str());
//         return buffer;   
//     }

//     std::string Rerrno_To_string()
//     {
//         switch(_rerrno)
//         {
//             case 0:
//                 return "Correct";
//             case 1:
//                 return "Zero";
//             default:
//                 return "Unknown";
//         }
//     }
// private:
//     T _data1;
//     T _data2;
//     char _rule;
//     T _result;
//     int _rerrno;
// };
// 在设计线程池时，我们最主要的两个成员变量为：共享资源和N个新线程\
// 剩下其他的成员变量都是基于这两者来进行增补的\
// 而成员函数主要是 主线程派发任务 和 新线程拿到任务并处理\
// 其他成员函数自行增补
// template <class T>
// class ThreadPool;
// #pragma once
// #include <iostream>
// #include <pthread.h>
// #include <queue>  //用作 共享资源
// #include <vector> //用作 存放线程们
// #include "Threads.hpp"
// #include "ProtectResourse.hpp"
// #include "Log.hpp"
// #define THREADSIZE 5 // 线程组中线程的个数
// // 这里模版给的是共享资源的内容类型，可以派发内置类型，也可以派发自定义类型
// template <class T>
// class ThreadPool
// {
// public:
//     //构造函数【OK】
//     ThreadPool(int size = THREADSIZE)
//         : _thread_size(size)
//     {
//         // 初始化线程组
//         for (int i = 0; i < size; ++i)
//         {
//             _threads.emplace_back
//             (
//                 //////////////////////////////////////////
//                 //////////// 重点 ////////////////////////
//                 std::bind(&ThreadPool<T>::Run, 
//                           this, 
//                           std::placeholders::_1, 
//                           std::placeholders::_2)
//                 , 0
//             );
//         }

//         pthread_mutex_init(&_mutex, nullptr);
//         pthread_cond_init(&_cond, nullptr);
//     }
//     //析构函数【OK】
//     ~ThreadPool()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_cond);
//     }

//     // 主线程派发任务【OK】
//     void Push(T &task)
//     {
//         ProtectResourse protect(&_mutex);
//         {
//             static int i = 0;
//             _shared_resourse.push(task);
//             Log log;
//             log.LogMessage(ClassFile, Debug + i++, 
//                            "main thread push a task : %s\n", task.TaskPrint().c_str());
//             i %= 4;
//             One_Thread_Wakeup();
//         }
//     }
    
//     // 线程组执行任务【OK】
//     void Start_Task()
//     {
//         for (auto &e : _threads)
//         {
//             e.Start();
//         }
//     }

//     // 回收线程组【OK】
//     void Join_Threads()
//     {
//         for (auto &e : _threads)
//         {
//             e.Join();
//         }
//     }

// private:
//     std::queue<T> _shared_resourse;            // 存放任务的共享资源
//     int _thread_size;                          // 线程组中线程的个数
//     std::vector< Thread<void* ,int> > _threads; // 线程组
//     pthread_mutex_t _mutex;                    // 线程组之间互斥访问共享资源的锁
//     pthread_cond_t _cond;                      // 主线程与线程组之间要保持同步&&互斥时使用的条件变量

// ////////////////////////////////////////////////////////////////////////////
//     void *Run(std::string name, int arg)   //重点！！！！！！！
//     {
//         static int i = 0;
//         T task;
//         while (true)
//         {
//             ProtectResourse protect(&_mutex);
//             {
//                 while(_shared_resourse.empty())
//                 {
//                     Thread_Wait();
//                 }

//                 // 拿任务
//                 task = _shared_resourse.front();
//                 _shared_resourse.pop();
//             }
//             // 处理任务
//             task.Run();
//             Log log;
//             log.LogMessage(ClassFile, Debug + i++, 
//                            "%s : %s\n", name.c_str(),  task.ResultPrint().c_str());
//             i %= 4;
//         }
//         return nullptr;
//     }

//     //唤醒一个线程 【OK】
//     void One_Thread_Wakeup()
//     {
//         pthread_cond_signal(&_cond);
//     }
//     //唤醒所有线程 【OK】
//     void All_Thread_Wakeup()
//     {
//         pthread_cond_broadcast(&_cond);
//     }
//     //没有资源了，让线程组等待 【OK】
//     void Thread_Wait()
//     {
//         pthread_cond_wait(&_cond, &_mutex);
//     }
// };// 本hpp用于 <<封装自己的线程相关接口，给线程添加更多属性>> 方便测试查看
// // 可用于学习，不可进行抄袭、转载、更改等对原创知识有害的操作，如需转载分享，请标明出处

// #pragma once
// #include <pthread.h>
// #include <string>
// #include <functional>

// // 形同于：typedef std::function<void*(void*)> func_t
// template <class R, class V>
// using func_t = std::function<R(std::string, V)>;

// template <class R, class V>
// class Thread
// {
// public:
//     Thread(func_t<R, V> func, V arg)
//         : _thread(0)
//         , _thread_name()
//         , _attr(pthread_attr_t())
//         , _istunning(false)
//         , _func(func)
//         , _arg(arg)
//     {
//         _thread_name = Create_Thread_Name();
//     }

//     // 开始让线程执行对应方法
//     void Start()
//     {
//         _istunning = true;
//         // 前两个都为输出型参数，可以得到线程ID与属性集
//         pthread_create(&_thread, &_attr, Function, (void *)this);
//     }

//     // 等待线程
//     void Join()
//     {
//         // 可以得到thread执行完函数方法的返回值信息
//         pthread_join(_thread, &_return_message);
//         _istunning = false;
//     }

//     //拿到线程的成员变量
//     pthread_t tid() {return _thread;}
//     std::string& name() {return _thread_name;}
//     const pthread_attr_t& attr() {return _attr;}
//     bool Isrunning() {return _istunning;}
//     R& re_message() {return reinterpret_cast<R>(_return_message);}

// private:
//     pthread_t _thread;          // 线程ID
//     std::string _thread_name;   // 线程名字 
//     const pthread_attr_t _attr; // 线程属性集
//     bool _istunning;            // 线程是否运行
//     void *_return_message;      // 线程执行完对应方法的返回值信息
//     func_t<R, V> _func;         // 线程执行的函数方法
//     V _arg;                     // 函数方法的参数

//     // 这么写Functuon的原因:我们可以通过伪造一个void*(*)(void*)类型的函数
//     // 但是在函数内部可以用来回调我们在main.cc中的函数方法
//     // 通过第二个参数传this指针，可以找到_func和_arg
//     // 至此可以让我们成功回调我们自定义的函数方法
//     static void *Function(void *arg)
//     {
//         Thread<R, V> *pThread = static_cast<Thread<R, V> *>(arg);
//         return reinterpret_cast<void*>(pThread->_func(pThread->_thread_name, pThread->_arg));
//     }

//     std::string Create_Thread_Name()
//     {
//         std::string name = "thread-";
//         static int i = 1; //定义一个局部的静态变量，作用域是该函数内有效，生命周期为全局的
//         name += std::to_string(i++);
//         return name;
//     }
// };